﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Comsenz.Base;
using Comsenz.UCenter.Configs;
using Lbb.Security;
using Lbb.Web;

/*
#if DEBUG
using System.Diagnostics;
#endif
*/

namespace Comsenz.UCenter.Client
{
    /// <summary>
    /// 同步助理,同步数据到 Comsenz UCenter.
    /// </summary>
    /// <Author>Chiron</Author>
    /// <remarks>Comsenz UCenter V1.6.0</remarks>
    public static class UcSyncHelper
    {
        #region Fields

        /// <summary>
        /// 发放代码
        /// </summary>
        public const string UC_CLIENT_RELEASE = "20110501";

        /// <summary>
        /// 接口版本
        /// </summary>
        public const string UC_CLIENT_VERSION = "1.6.0";

        #endregion Fields

        #region Helpers

        #region Convert Helpers

        /// <summary>
        /// 转为数值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static int ToInt(string value)
        {
            try
            {
                return int.Parse(value);
            }
            catch
            {
                throw new Exception(string.IsNullOrEmpty(value) ? "不能将空值转换成 int." : value);
            }
        }

        /// <summary>
        /// 转为列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private static List<T> ToList<T>(string value)
            where T : class
        {
            var result = XmlHelper.UnSerialize(value);

            if (result != null)
            {
                return result.Select(d => d.Value as T).ToList();
            }
            throw new Exception(string.IsNullOrEmpty(value) ? "不能将空值转换成列表 ." : value);
        }

        /// <summary>
        /// 转为字典
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Dictionary<TKey, TValue> ToDict<TKey, TValue>(string value)
            where TKey : class
            where TValue : class
        {
            var result = XmlHelper.UnSerialize(value);
            if (result != null)
            {
                return result.ToDictionary(d => d.Key as TKey, d => d.Value as TValue);
            }
            throw new Exception(string.IsNullOrEmpty(value) ? "不能将空值传成字典 ." : value);
        }

        /// <summary>
        /// 转为字典列表
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private static List<Dictionary<TKey, TValue>> ToDictList<TKey, TValue>(string value)
            where TKey : class
            where TValue : class
        {
            var result = XmlHelper.UnSerialize(value);
            if (result != null)
            {
                try
                {
                    return result.Select(d =>
                    {
                        var tValue = d.Value as Dictionary<object, object>;
                        if (tValue != null) return tValue.ToDictionary(e => e.Key as TKey, e => e.Value as TValue);
                        return null;
                    }).Where(d => d != null).ToList();
                }
                catch { }
            }
            throw new Exception(string.IsNullOrEmpty(value) ? "不能将空值转换成字典列表." : value);
        }

        #endregion Convert Helpers

        /// <summary>
        /// 取得用户代理的MD5编码
        /// </summary>
        /// <returns></returns>
        private static string GetUserAgentMd5Code()
        {
            return HttpContext.Current == null ? "d41d8cd98f00b204e9800998ecf8427e" : Cryptography.MD5(HttpContext.Current.Request.UserAgent);
        }

        #endregion Helpers

        #region API Base Methods

        /// <summary>
        /// 字符串加密以及解密函数
        /// </summary>
        /// <param name="data">原文或者密文</param>
        /// <param name="operation">操作(ENCODE | DECODE), 默认为 DECODE</param>
        /// <param name="key">密钥, 默认为 Config.ConnectKey</param>
        /// <param name="expiry">密文有效期, 加密时候有效， 单位 秒，0 为永久有效</param>
        /// <param name="ckey_length">
        /// 随机密钥长度 取值 0-32;默认为 4;
        /// 加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
        /// 取值越大，密文变动规律越大，密文变化 = 16 的 ckey_length 次方.
        /// 当此值为 0 时，则不产生随机密钥.
        /// </param>
        /// <returns>处理后的 原文或者 经过 base64_encode 处理后的密文</returns>
        public static string uc_authcode(string data, string operation = "DECODE", string key = null, int expiry = 0, int ckey_length = 4)
        {
            if (string.IsNullOrEmpty(data)) throw new ArgumentNullException("data");

            #region Debug
            /*
#if DEBUG
            Debug.WriteLine(null);
            Debug.Print("Debuging uc_authcode {0}.", operation);
            Debug.Print("SourceData:{0}", data);
            Debug.WriteLine(null);

#endif
             */
            #endregion Debug

            if (ckey_length < 0) ckey_length = 0;
            else if (ckey_length > 32) ckey_length = 32;

            key = Cryptography.MD5(key ?? UCenterConfig.Instance.CurrentConnectConfig.ConnectKey);
            var keya = Cryptography.MD5(key.Substring(0, 16));
            var keyb = Cryptography.MD5(key.Substring(16, 16));
            var keyc = ckey_length > 0 ?
                (operation == "DECODE" ? data.Substring(0, ckey_length) : Cryptography.MD5(PhpFunc.Microtime()).Substring(32 - ckey_length)) :
                string.Empty;

            var cryptkey = keya + Cryptography.MD5(keya + keyc);

            var tdata = data;
            if (operation == "DECODE")
            {
                tdata = data.Substring(ckey_length);
                if (tdata.Length % 4 != 0) tdata += new string('=', 4 - (tdata.Length % 4));
            }

            var dataBuf = operation == "DECODE" ?
                Convert.FromBase64String(tdata) :
                ((expiry < 1 ? 0 : PhpFunc.Time() + expiry).ToString("000000000#") + Cryptography.MD5(data + keyb).Substring(0, 16) + data).Select(d => (byte)d).ToArray();

            #region Debug
            /*
#if DEBUG
            Debug.Print("key:{0}\nkeya:{1}\nkeyb:{2}\nkeyc:{3}\ncryptkey:{4}", key, keya, keyb, keyc, cryptkey);
            Debug.Print("DataBuf:{0}", dataBuf.Select(d => ((int)d).ToString()).Aggregate((d, e) => d + e));
            Debug.WriteLine(null);
#endif
             */
            #endregion Debug


            var rndkey = new char[256];
            var box = new char[256];
            for (var i = 0; i < 256; i++)
            {
                box[i] = (char)i;
                rndkey[i] = cryptkey[i % cryptkey.Length];
            }

            for (int i = 0, j = 0; i < 256; i++)
            {
                j = (j + box[i] + rndkey[i]) % 256;
                var tmp = box[i];
                box[i] = box[j];
                box[j] = tmp;
            }

            #region Debug
            /*
#if DEBUG
            Debug.Print("rndkey:{0}", new string(rndkey));
            Debug.Print("box:{0}", box.Select(d => ((int)d).ToString()).Aggregate((d, e) => d + e));
            Debug.WriteLine(null);
#endif
            */
            #endregion Debug

            var resultBuf = new byte[dataBuf.Length];
            for (int a = 0, j = 0, i = 0; i < dataBuf.Length; i++)
            {
                a = (a + 1) % 256;
                j = (j + box[a]) % 256;
                var tmp = box[a];
                box[a] = box[j];
                box[j] = tmp;
                resultBuf[i] = (byte)(dataBuf[i] ^ box[(box[a] + box[j]) % 256]);
            }

            var result = Encoding.UTF8.GetString(resultBuf);    //TODO:待解决，非英文字符不能正常解码      Chiron

            #region Debug
            /*
#if DEBUG
            Debug.Print("resultBuf:{0}", resultBuf.Select(d => ((int)d).ToString()).Aggregate((d, e) => d + e));
            Debug.Print("result:{0}", result);
            Debug.WriteLine(null);
#endif
            */
            #endregion Debug

            if (operation == "DECODE")
            {
                int tTime;
                int.TryParse(result.Substring(0, 10), out tTime);
                if ((tTime == 0 || tTime - PhpFunc.Time() > 0) && result.Substring(10, 16) == Cryptography.MD5(result.Substring(26) + keyb).Substring(0, 16))
                {
                    return result.Substring(26);
                }
                else
                {
                    return string.Empty;
                }
            }
            else
            {
                return keyc + Convert.ToBase64String(resultBuf).Replace("=", string.Empty);
            }
        }

        /// <summary>
        /// 构建参数
        /// </summary>
        /// <param name="data">参数</param>
        /// <returns></returns>
        public static string uc_api_input(string data)
        {
            var agent = "&agent=" + GetUserAgentMd5Code();
            return HttpUtility.UrlEncode(uc_authcode(data + agent + "&time=" + PhpFunc.Time(), "ENCODE"));
        }

        /// <summary>
        /// 构造发送给用户中心的请求数据
        /// </summary>
        /// <param name="module">请求的模块</param>
        /// <param name="action">请求的动作</param>
        /// <param name="arg">参数（会加密的方式传送）</param>
        /// <param name="extra">附加参数（传送时不加密）</param>
        /// <returns>用户中心处理后的反馈</returns>
        public static string uc_api_requestdata(string module, string action, string arg = null, string extra = null)
        {
            var input = "&input=" + uc_api_input(arg ?? string.Empty);
            return "m=" + module + "&a=" + action + "&inajax=2&release=" + UC_CLIENT_RELEASE + input + "&appid=" + UCenterConfig.Instance.CurrentConnectConfig.AppId + extra ?? string.Empty;
        }

        /// <summary>
        /// 构建请求路径
        /// </summary>
        /// <param name="module">请求的模块</param>
        /// <param name="action">请求的动作</param>
        /// <param name="arg">参数</param>
        /// <param name="extra">附加参数</param>
        /// <returns>反馈数据</returns>
        public static string uc_api_url(string module, string action, string arg = null, string extra = null)
        {
            return UCenterConfig.Instance.CurrentConnectConfig.ApiUri + "?" + uc_api_requestdata(module, action, arg, extra);
        }

        /// <summary>
        /// Web接口方式取指定的模块和动作的数据
        /// </summary>
        /// <param name="module">请求的模块</param>
        /// <param name="action">请求的动作</param>
        /// <param name="arg">参数</param>
        /// <returns>反馈数据</returns>
        public static string uc_api_post(string module, string action, IEnumerable<QueryParameter> arg = null)
        {
            string s = "", sep = "", qpv;
            if (arg != null)
            {
                foreach (var qp in arg)
                {
                    qpv = qp.ToUrlEncodedString();
                    if (!string.IsNullOrEmpty(qpv))
                    {
                        s += sep + qpv;
                        sep = "&";
                    }
                }
            }

            var postdata = uc_api_requestdata(module, action, s);
            return HttpHelper.HttpGet(UCenterConfig.Instance.CurrentConnectConfig.ApiUri, postdata);
        }

        #endregion API Base Methods

        #region API

        #region 用户接口
        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="email">Email</param>
        /// <param name="questionid">安全提问</param>
        /// <param name="answer">安全提问答案</param>
        /// <param name="regip"></param>
        /// <returns>
        /// -1 : 用户名不合法,
        /// -2 : 包含不允许注册的词语,
        /// -3 : 用户名已经存在,
        /// -4 : email 格式有误,
        /// -5 : email 不允许注册,
        /// -6 : 该 email 已经被注册,
        /// >0 : 表示成功，数值为 UID.
        /// </returns>
        public static int uc_user_register(string username, string password, string email, string questionid = null, string answer = null, string regip = null)
        {
            if (string.IsNullOrEmpty(username)) new ArgumentNullException("username");
            if (string.IsNullOrEmpty(password)) new ArgumentNullException("password");
            if (string.IsNullOrEmpty(email)) new ArgumentNullException("email");
            if (!string.IsNullOrEmpty(questionid) && string.IsNullOrEmpty(answer)) new ArgumentNullException("answer");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            arg.Add("password", password);
            arg.Add("email", email);
            arg.Add("questionid", questionid ?? string.Empty);
            arg.Add("answer", answer ?? string.Empty);
            arg.Add("regip", regip ?? string.Empty);
            return ToInt(uc_api_post("user", "register", arg));
        }

        /// <summary>
        /// 用户登陆检查
        /// </summary>
        /// <param name="username">用户名/uid</param>
        /// <param name="password">密码</param>
        /// <param name="isuid">是否为uid</param>
        /// <param name="checkques">是否使用检查安全问答</param>
        /// <param name="questionid">安全提问</param>
        /// <param name="answer">安全提问答案</param>
        /// <returns>
        /// array (uid/status, username, password, email);
        /// 数组第一项:
        /// 1  : 成功,
        /// -1 : 用户不存在,或者被删除,
        /// -2 : 密码错.
        /// </returns>
        public static List<string> uc_user_login(string username, string password, int isuid = 0, int checkques = 0, string questionid = null, string answer = null)
        {
            if (string.IsNullOrEmpty(username)) new ArgumentNullException("username");
            if (string.IsNullOrEmpty(password)) new ArgumentNullException("password");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            arg.Add("password", password);
            arg.Add("isuid", isuid);
            arg.Add("checkques", checkques);
            arg.Add("questionid", questionid ?? string.Empty);
            arg.Add("answer", answer ?? string.Empty);

            return ToList<string>(uc_api_post("user", "login", arg));

        }



        /// <summary>
        /// 进入同步登录代码
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <returns>HTML代码</returns>
        public static string uc_user_synlogin(int uid)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            return uc_api_post("user", "synlogin", arg);
        }

        /// <summary>
        /// 进入同步登出代码
        /// </summary>
        /// <returns>HTML代码</returns>
        public static string uc_user_synlogout()
        {
            return uc_api_post("user", "synlogout");
        }

        /// <summary>
        /// 编辑用户
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="oldpw">旧密码</param>
        /// <param name="newpw">新密码</param>
        /// <param name="email">Email</param>
        /// <param name="ignoreoldpw">是否忽略旧密码, 忽略旧密码, 则不进行旧密码校验.</param>
        /// <param name="questionid">安全提问</param>
        /// <param name="answer">安全提问答案</param>
        /// <returns>
        /// 1  : 修改成功,
        /// 0  : 没有任何修改,
        /// -1 : 旧密码不正确,
        /// -4 : email 格式有误,
        /// -5 : email 不允许注册,
        /// -6 : 该 email 已经被注册,
        /// -7 : 没有做任何修改,
        /// -8 : 受保护的用户，没有权限修改.
        /// </returns>
        public static int uc_user_edit(string username, string oldpw, string newpw, string email, bool ignoreoldpw = false, string questionid = null, string answer = null)
        {
            if (string.IsNullOrEmpty(username)) new ArgumentNullException("username");
            if (ignoreoldpw && string.IsNullOrEmpty(oldpw)) new ArgumentNullException("oldpw");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            arg.Add("oldpw", oldpw ?? string.Empty);
            arg.Add("newpw", newpw ?? string.Empty);
            arg.Add("email", email ?? string.Empty);
            arg.Add("ignoreoldpw", ignoreoldpw ? 1 : 0);
            arg.Add("questionid", questionid ?? string.Empty);
            arg.Add("answer", answer ?? string.Empty);
            return ToInt(uc_api_post("user", "edit", arg));
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="uid">用户的 UID</param>
        /// <returns>
        /// >0 : 成功
        /// 0 : 失败
        /// </returns>
        public static int uc_user_delete(int uid)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            return ToInt(uc_api_post("user", "delete", arg));
        }

        /// <summary>
        /// 删除用户头像
        /// </summary>
        /// <param name="uid">用户的 UID</param>
        public static void uc_user_deleteavatar(int uid)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            uc_api_post("user", "deleteavatar", arg);
        }

        /// <summary>
        /// 修改头像
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="type">头像类型 real OR virtual 默认为 virtual</param>
        /// <param name="returnhtml"></param>
        /// <returns></returns>
        public static object uc_avatar(int uid, string type = "virtual", bool returnhtml = true, int width = 450, int height = 253)
        {
            var connConfig = UCenterConfig.Instance.CurrentConnectConfig;
            var uc_input = uc_api_input("uid=" + uid);
            var userAgent = "&agent=" + GetUserAgentMd5Code();
            var uc_avatarflash = connConfig.ApiUri + "/images/camera.swf?inajax=1&appid=" + connConfig.AppId + "&input=" + uc_input + userAgent + "&ucapi=" + HttpUtility.UrlEncode(connConfig.ApiUri) + "&avatartype=" + type;
            if (returnhtml)
            {
                return @"<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' width='" + width + @"' height='" + height + @"' id='mycamera' align='middle'>
    <param name='allowScriptAccess' value='always' />
    <param name='scale' value='exactfit' />
    <param name='wmode' value='transparent' />
    <param name='quality' value='high' />
    <param name='bgcolor' value='#ffffff' />
    <param name='movie' value='" + uc_avatarflash + @"' />
    <param name='menu' value='false' />
    <embed src='" + uc_avatarflash + @"' quality='high' bgcolor='#ffffff' width='" + width + @"' height='" + height + @"' name='mycamera' align='middle' allowScriptAccess='always' allowFullScreen='false' scale='exactfit'  wmode='transparent' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer' />
</object>";
            }
            else
            {
                return new Dictionary<string, string>{
                    {"width",width.ToString()},
                    {"height",height.ToString()},
                    {"scale","exactfit"},
                    {"src",uc_avatarflash},
                    {"id","mycamera"},
                    {"name","mycamera"},
                    {"quality","high"},
                    {"bgcolor","#ffffff"},
                    {"wmode","transparent"},
                    {"menu","false"},
                    {"swLiveConnect","true"},
                    {"allowScriptAccess","always"}
                };
            }
        }

        /// <summary>
        /// 检测是否存在指定头像
        /// </summary>
        /// <param name="uid">用户id</param>
        /// <param name="size">头像尺寸，取值范围(big,middle,small)，默认为 middle</param>
        /// <param name="type">头像类型，取值范围(virtual,real)，默认为virtual</param>
        /// <returns>
        /// true : 头像存在
        /// false: 头像不存在
        /// </returns>
        public static bool uc_check_avatar(int uid, string size = "middle", string type = "virtual")
        {
            var url = UCenterConfig.Instance.CurrentConnectConfig.ApiUri + "/avatar.php?uid=" + uid + "&size=" + size + "&type=" + type + "&check_file_exists=1";
            return ToInt(HttpHelper.HttpGet(url)) > 0;
        }


        /// <summary>
        /// 检查用户名是否为合法
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>
        /// 1 : 合法
        /// -1 : 用户名不合法
        /// -2 : 包含不允许注册的词语
        /// -3 : 用户名已经存在
        /// </returns>
        public static int uc_user_checkname(string username)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            return ToInt(uc_api_post("user", "check_username", arg));
        }

        /// <summary>
        /// 检查Email地址是否正确
        /// </summary>
        /// <param name="email">Email</param>
        /// <returns>
        /// 1  : 成功
        /// -4 : email 格式有误
        /// -5 : email 不允许注册
        /// -6 : 该 email 已经被注册
        /// </returns>
        public static int uc_user_checkemail(string email)
        {
            if (string.IsNullOrEmpty(email)) throw new ArgumentNullException("email");

            var arg = new List<QueryParameter>();
            arg.Add("email", email);
            return ToInt(uc_api_post("user", "check_email", arg));
        }

        /// <summary>
        /// 添加保护用户
        /// </summary>
        /// <param name="username">保护用户名</param>
        /// <param name="admin">操作的管理员</param>
        /// <returns>
        /// -1 : 失败
        /// 1 : 成功
        /// </returns>
        public static int uc_user_addprotected(string username, string admin = null)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            arg.Add("admin", admin);
            return ToInt(uc_api_post("user", "addprotected", arg));
        }

        /// <summary>
        /// 删除保护用户
        /// </summary>
        /// <param name="username">保护用户名</param>
        /// <returns>
        /// -1 : 失败
        /// 1 : 成功
        /// </returns>
        public static int uc_user_deleteprotected(string username)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            return ToInt(uc_api_post("user", "deleteprotected", arg));
        }

        /// <summary>
        /// 得到受保护的用户名列表
        /// </summary>
        /// <returns>受到保护的用户名列表</returns>
        public static List<Dictionary<string, string>> uc_user_getprotected()
        {
            var arg = new List<QueryParameter>();
            arg.Add("1", 1);

            return ToDictList<string, string>(uc_api_post("user", "getprotected", arg));
        }

        /// <summary>
        /// 取得用户数据
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="isuid">是否为UID</param>
        /// <returns>array (uid, username, email)</returns>
        public static List<string> uc_get_user(string username, int isuid = 0)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);
            arg.Add("isuid", isuid);

            var result = uc_api_post("user", "get_user", arg);
            return result != "0" ? ToList<string>(result) : null;
        }

        /// <summary>
        /// 用户合并最后的处理
        /// </summary>
        /// <param name="oldusername">老用户名</param>
        /// <param name="newusername">新用户名</param>
        /// <param name="uid">老UID</param>
        /// <param name="password">密码</param>
        /// <param name="email">Email</param>
        /// <returns>
        /// -1 : 用户名不合法
        /// -2 : 包含不允许注册的词语
        /// -3 : 用户名已经存在
        /// >1 : 表示成功，数值为 UID
        /// </returns>
        public static int uc_user_merge(string oldusername, string newusername, int uid, string password, string email)
        {
            if (string.IsNullOrEmpty(oldusername)) throw new ArgumentNullException("oldusername");
            if (string.IsNullOrEmpty(newusername)) throw new ArgumentNullException("newusername");

            var arg = new List<QueryParameter>();
            arg.Add("oldusername", oldusername);
            arg.Add("newusername", newusername);
            arg.Add("uid", uid);
            arg.Add("password", password);
            arg.Add("email", email);

            return ToInt(uc_api_post("user", "merge", arg));
        }

        /// <summary>
        /// 移去合并用户记录
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static void uc_user_merge_remove(string username)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            var arg = new List<QueryParameter>();
            arg.Add("username", username);

            uc_api_post("user", "merge_remove", arg);
        }

        #endregion 用户接口

        #region 用户配置文件接口
        /// <summary>
        /// 取得用户属性值
        /// </summary>
        /// <param name="uid">用户标识</param>
        /// <param name="field">属性字段名</param>
        /// <returns>属性值</returns>
        public static string uc_user_getprofile(int uid, string field)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("field", field);
            return uc_api_post("userprofile", "get", arg);
        }
        #endregion 用户配置文件接口

        #region 积分接口

        /// <summary>
        /// 获取指定应用的指定用户积分值
        /// </summary>
        /// <param name="appid">应用Id</param>
        /// <param name="uid">用户Id</param>
        /// <param name="credit">积分编号</param>
        public static int uc_user_getcredit(int appid, int uid, int credit)
        {
            var arg = new List<QueryParameter>();
            arg.Add("appid", appid);
            arg.Add("uid", uid);
            arg.Add("credit", credit);
            return ToInt(uc_api_post("user", "getcredit", arg));
        }

        /// <summary>
        /// 积分兑换请求
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="from">原积分</param>
        /// <param name="to">目标积分</param>
        /// <param name="toappid">目标应用ID</param>
        /// <param name="amount">积分数额</param>
        /// <returns>
        /// 1  : 成功
        /// 0  : 失败
        /// </returns>
        public static int uc_credit_exchange_request(int uid, int from, int to, int toappid, int amount)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("from", from);
            arg.Add("to", to);
            arg.Add("toappid", toappid);
            arg.Add("amount", amount);

            return ToInt(uc_api_post("credit", "request", arg));
        }


        #endregion 积分接口

        #region 短消息接口

        /// <summary>
        /// 进入短消息界面
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="newpm">是否直接进入newpm</param>
        /// <returns></returns>
        public static string uc_pm_location(int uid, bool newpm = false)
        {
            return uc_api_url("pm_client", "ls", "uid=" + uid, newpm ? "&folder=newbox" : string.Empty);
        }

        /// <summary>
        /// 检查新短消息
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="more">详细信息</param>
        /// <returns>
        /// 是否存在新短消息
        /// 2	详细	(短消息数、公共消息数、最后消息时间, 最后消息内容)
        /// 1	简单	(短消息数、公共消息数、最后消息时间)
        /// 0	否
        /// </returns>
        public static int uc_pm_checknew(int uid, int more = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("more", more);

            return ToInt(uc_api_post("pm", "check_newpm", arg));
        }

        /// <summary>
        /// 发送短消息
        /// </summary>
        /// <param name="fromuid">发件人uid 0 为系统消息</param>
        /// <param name="msgto">收件人 uid/username 多个逗号分割</param>
        /// <param name="subject">标题</param>
        /// <param name="message">内容</param>
        /// <param name="instantly">立即发送 true 立即发送(默认)  false 进入短消息发送界面</param>
        /// <param name="replypmid">回复的消息Id</param>
        /// <param name="isusername">0 = $msgto 为 uid、1 = $msgto 为 username</param>
        /// <returns>
        /// instantly 为 true 时
        ///     >1	发送成功的人数
        ///     0	收件人不存在
        /// instantly 为 false 时
        ///     重定向地址
        /// </returns>
        public static string uc_pm_send(int fromuid, string msgto, string subject, string message, bool instantly = true, int replypmid = 0, int isusername = 0)
        {
            if (string.IsNullOrEmpty(subject)) throw new ArgumentNullException("subject");
            if (string.IsNullOrEmpty(message)) throw new ArgumentNullException("message");

            if (instantly)
            {
                var arg = new List<QueryParameter>();
                arg.Add("fromuid", fromuid);
                arg.Add("msgto", msgto);
                arg.Add("subject", subject);
                arg.Add("message", message);
                arg.Add("replypmid", replypmid);
                arg.Add("isusername", isusername);

                return uc_api_post("pm", "sendpm", arg);
            }
            else
            {
                var replyadd = replypmid != 0 ? "&pmid=$replypmid&do=reply" : string.Empty;
                return uc_api_url("pm_client", "send", "uid=" + fromuid, "&msgto=" + msgto + "&subject=" + subject + "&message=" + message + replyadd);
            }
        }

        /// <summary>
        /// 删除短消息
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="folder">打开的目录 inbox=收件箱，outbox=发件箱</param>
        /// <param name="pmids">要删除的消息ID数组</param>
        /// <returns>
        /// 大于 0 成功
        /// 小于等于 0 失败
        /// </returns>
        public static int uc_pm_delete(int uid, string folder, int[] pmids)
        {
            if (string.IsNullOrEmpty(folder)) throw new ArgumentNullException("folder");
            if (pmids == null) throw new ArgumentNullException("pmids");

            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("folder", folder);
            arg.AddRange(QueryParameter.ArrayQueryParameter("pmids", pmids));

            return ToInt(uc_api_post("pm", "delete", arg));
        }

        /// <summary>
        /// 按照用户删除短消息
        /// </summary>
        /// <param name="uid">发用户Id</param>
        /// <param name="touids">收用户Id</param>
        /// <returns></returns>
        public static int uc_pm_deleteuser(int uid, int[] touids)
        {
            if (touids == null) throw new ArgumentNullException("touids");

            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.AddRange(QueryParameter.ArrayQueryParameter("touids", touids));

            return ToInt(uc_api_post("pm", "deleteuser", arg));
        }

        /// <summary>
        /// 标记已读/未读状态
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="uids">要标记已读状态的用户ID数组</param>
        /// <param name="pmids">要标记已读状态的消息ID数组</param>
        /// <param name="status">1 已读 0 未读</param>
        /// <returns></returns>
        public static void uc_pm_readstatus(int uid, int[] uids, int[] pmids = null, int status = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.AddRange(QueryParameter.ArrayQueryParameter("uids", uids));
            arg.AddRange(QueryParameter.ArrayQueryParameter("pmids", pmids));
            arg.Add("status", status);

            uc_api_post("pm", "readstatus", arg);
        }

        /// <summary>
        /// 获取短消息列表
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="page">当前页</param>
        /// <param name="pagesize">每页最大条目数</param>
        /// <param name="folder">打开的目录 newbox=未读消息，inbox=收件箱，outbox=发件箱</param>
        /// <param name="filter">
        /// 过滤方式 newpm=未读消息，systempm=系统消息，announcepm=公共消息
        /// $folder		$filter
        /// --------------------------
        /// newbox
        /// inbox		newpm
        /// 			systempm
        ///     		announcepm
        /// outbox		newpm
        /// searchbox	*
        /// </param>
        /// <param name="msglen">截取的消息文字长度</param>
        /// <returns>array('count' => 消息总数, 'data' => 短消息数据)</returns>
        public static Dictionary<string, object> uc_pm_list(int uid, int page = 1, int pagesize = 10, string folder = "inbox", string filter = "newpm", int msglen = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("page", page);
            arg.Add("pagesize", pagesize);
            arg.Add("folder", folder);
            arg.Add("filter", filter);
            arg.Add("msglen", msglen);

            return ToDict<string, object>(uc_api_post("pm", "ls", arg));
        }



        /// <summary>
        /// 忽略未读消息提示
        /// </summary>
        /// <param name="uid">用户Id</param>
        public static int uc_pm_ignore(int uid)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);

            return ToInt(uc_api_post("pm", "ignore", arg));
        }

        /// <summary>
        /// 获取短消息内容
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="pmid">消息Id</param>
        /// <param name="touid">消息对方用户Id</param>
        /// <param name="daterange">日期范围 1=今天,2=昨天,3=前天,4=上周,5=更早</param>
        /// <returns>短消息内容数组</returns>
        public static List<Dictionary<string, string>> uc_pm_view(int uid, int pmid, int touid = 0, int daterange = 1)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("pmid", pmid);
            arg.Add("touid", touid);
            arg.Add("daterange", daterange);

            return ToDictList<string, string>(uc_api_post("pm", "view", arg));
        }

        /// <summary>
        /// 获取单条短消息内容
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="type">
        /// 0 = 获取指定单条消息,
        /// 1 = 获取指定用户发的最后单条消息,
        /// 2 = 获取指定用户收的最后单条消息.
        /// </param>
        /// <param name="pmid">消息Id</param>
        /// <returns>短消息内容数组</returns>
        public static List<string> uc_pm_viewnode(int uid, int type = 0, int pmid = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("pmid", pmid);
            arg.Add("type", type);

            return ToList<string>(uc_api_post("pm", "viewnode", arg));
        }

        /// <summary>
        /// 获取黑名单
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <returns>黑名单内容</returns>
        public static string uc_pm_blackls_get(int uid)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);

            return uc_api_post("pm", "blackls_get", arg);
        }

        /// <summary>
        /// 设置黑名单
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="blackls">黑名单内容</param>
        /// <returns></returns>
        public static int uc_pm_blackls_set(int uid, string blackls)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("blackls", blackls);

            return ToInt(uc_api_post("pm", "blackls_set", arg));
        }

        /// <summary>
        /// 添加黑名单项目
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static int uc_pm_blackls_add(int uid, string username)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("username", username);

            return ToInt(uc_api_post("pm", "blackls_add", arg));
        }

        /// <summary>
        /// 删除黑名单项目
        /// </summary>
        /// <param name="uid">用户Id</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static int uc_pm_blackls_delete(int uid, string username)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("username", username);

            return ToInt(uc_api_post("pm", "blackls_delete", arg));
        }

        #endregion 短消息接口

        #region 标签接口

        /// <summary>
        /// 返回指定的相关TAG数据
        /// </summary>
        /// <param name="tagname">TAG名称</param>
        /// <param name="nums">返回数据的条目数</param>
        /// <returns>序列化过的数组，数组内容为当前或其他应用的相关TAG数据</returns>
        public static List<Dictionary<string, string>> uc_tag_get(string tagname, int nums = 0)
        {
            if (string.IsNullOrEmpty(tagname)) throw new ArgumentNullException("tagname");

            var arg = new List<QueryParameter>();
            arg.Add("tagname", tagname);
            arg.Add("nums", nums);

            return ToDictList<string, string>(uc_api_post("tag", "gettag", arg));
        }

        #endregion 标签接口

        #region 应用接口
        /// <summary>
        /// 获取应用列表
        /// </summary>
        /// <returns></returns>
        public static List<Dictionary<string, string>> uc_app_ls()
        {
            return ToDictList<string, string>(uc_api_post("app", "ls"));
        }

        #endregion 应用接口

        #region 用户事件接口

        /// <summary>
        /// 添加用户事件
        /// </summary>
        /// <param name="icon">图标</param>
        /// <param name="uid">用户Id</param>
        /// <param name="username">用户名</param>
        /// <param name="title_template">标题模板</param>
        /// <param name="title_data">标题内容</param>
        /// <param name="body_template">内容模板</param>
        /// <param name="body_data">内容内容</param>
        /// <param name="body_general">保留</param>
        /// <param name="target_ids">保留</param>
        /// <param name="images">
        /// 图片
        /// 格式为:
        /// array(
        ///     array('url'=>'http://domain1/1.jpg', 'link'=>'http://domain1'),
        ///     array('url'=>'http://domain2/2.jpg', 'link'=>'http://domain2'),
        ///     array('url'=>'http://domain3/3.jpg', 'link'=>'http://domain3'),
        /// )
        /// </param>
        /// <returns>事件Id</returns>
        public static int uc_feed_add(string icon, int uid, string username, string title_template = null, IDictionary<string, string> title_data = null, string body_template = null, IDictionary<string, string> body_data = null, string body_general = null, string target_ids = null, IEnumerable<IDictionary<string, string>> images = null)
        {
            var arg = new List<QueryParameter>();
            arg.Add("icon", icon);
            arg.Add("appid", UCenterConfig.Instance.CurrentConnectConfig.AppId);
            arg.Add("uid", uid);
            arg.Add("username", username);
            arg.Add("title_template", title_template);
            arg.AddRange(QueryParameter.ArrayQueryParameter("title_data", title_data));
            arg.Add("body_template", body_template);
            arg.AddRange(QueryParameter.ArrayQueryParameter("body_data", body_data));
            arg.Add("body_general", body_general);
            arg.Add("target_ids", target_ids);

            if (images != null)
            {
                var n = images.Count();
                const string imgKeyFormat = "image_{0}";
                const string urlKey = "url";
                const string linkKey = "link";
                for (var i = 1; i <= n; i++)
                {
                    var item = images.ElementAt(i - 1);
                    if (item.ContainsKey(urlKey)) arg.Add(string.Format(imgKeyFormat, i), item[urlKey]);
                    if (item.ContainsKey(linkKey)) arg.Add(string.Format(imgKeyFormat, i + "_link"), item[linkKey]);
                }
            }

            return ToInt(uc_api_post("feed", "add", arg));
        }

        /// <summary>
        /// 取得用户事件列表
        /// </summary>
        /// <param name="limit">每次取多少条</param>
        /// <param name="delete">删除事件记录</param>
        /// <returns></returns>
        public static List<Dictionary<string, object>> uc_feed_get(int limit = 100, bool delete = true)
        {
            var arg = new List<QueryParameter>();
            arg.Add("limit", limit);
            arg.Add("delete", delete);

            return ToDictList<string, object>(uc_api_post("feed", "get", arg));
        }

        #endregion 用户事件接口

        #region 好友接口

        /// <summary>
        /// 添加好友
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="friendid">好友ID</param>
        /// <param name="comment">好友注释</param>
        /// <returns>
        /// 大于 0 成功
        /// 小于等于 0 失败
        /// </returns>
        public static int uc_friend_add(int uid, int friendid, string comment = null)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("friendid", friendid);
            arg.Add("comment", comment);

            return ToInt(uc_api_post("friend", "add", arg));
        }

        /// <summary>
        /// 删除好友
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="friendids">好友ID</param>
        /// <returns>
        /// 大于 0 成功
        /// 小于等于 0 失败,或者好友已经删除
        /// </returns>
        public static int uc_friend_delete(int uid, int[] friendids)
        {
            if (friendids == null) throw new ArgumentNullException("friendids");

            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.AddRange(QueryParameter.ArrayQueryParameter("friendids", friendids));

            return ToInt(uc_api_post("friend", "delete", arg));
        }

        /// <summary>
        /// 好友总数
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="direction">
        /// 0:(默认值) 指定用户的全部好友;
        /// 1:正向，指定用户添加的好友，但没被对方添加;
        /// 2:反向，指定用户被哪些用户添加为好友，但没被对方添加;
        /// 3:双向，互相添加为好友;
        /// 4:反向，指定用户被哪些用户添加为好友（粉丝）;
        /// </param>
        /// <returns></returns>
        public static int uc_friend_totalnum(int uid, int direction = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("direction", direction);

            return ToInt(uc_api_post("friend", "totalnum", arg));
        }

        /// <summary>
        /// 好友列表
        /// </summary>
        /// <param name="uid">用户ID</param>
        /// <param name="page">当前页编号，默认值 1</param>
        /// <param name="pagesize">每页最大条目数，默认值 10 </param>
        /// <param name="totalnum">好友总数，默认值 10</param>
        /// <param name="direction">
        /// 0:(默认值) 指定用户的全部好友
        /// 1:正向，指定用户添加的好友，但没被对方添加
        /// 2:反向，指定用户被哪些用户添加为好友（粉丝）
        /// 3:双向，互相添加为好友
        /// </param>
        /// <returns></returns>
        public static List<Dictionary<string, string>> uc_friend_ls(int uid, int page = 1, int pagesize = 10, int totalnum = 10, int direction = 0)
        {
            var arg = new List<QueryParameter>();
            arg.Add("uid", uid);
            arg.Add("page", page);
            arg.Add("pagesize", pagesize);
            arg.Add("totalnum", totalnum);
            arg.Add("direction", direction);

            return ToDictList<string, string>(uc_api_post("friend", "ls", arg));
        }


        #endregion 好友接口

        #region 系统接口

        /// <summary>
        /// 获取域名解析表
        /// </summary>
        /// <returns></returns>
        public static List<string> uc_domain_ls()
        {
            var arg = new List<QueryParameter>();
            arg.Add("1", 1);

            return ToList<string>(uc_api_post("domain", "ls", arg));
        }

        /// <summary>
        /// 邮件队列
        /// </summary>
        /// <param name="uids">用户名id，多个用逗号(,)隔开</param>
        /// <param name="emails">邮件地址，多个用逗号隔开</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="message">邮件内容</param>
        /// <param name="frommail">发件人</param>
        /// <param name="charset">邮件字符集，可选参数，默认为gbk</param>
        /// <param name="htmlon">是否按html格式发送邮件，可选参数，默认为否</param>
        /// <param name="level">邮件级别，可选参数，取值0-127，默认为1，越大发送的优先级越高，为0时不入库，直接发送，会影响当前进程速度，慎用</param>
        /// <returns>
        /// =0 : 失败
        /// >0 : 成功，返回插入记录的id，如果是多条则返回最后一条记录的id，若level等于0，则返回1
        /// </returns>
        public static int uc_mail_queue(string uids, string emails, string subject, string message, string frommail = null, string charset = "gbk", bool htmlon = false, int level = 1)
        {
            if (string.IsNullOrEmpty(emails)) throw new ArgumentNullException("emails");
            if (string.IsNullOrEmpty(subject)) throw new ArgumentNullException("subject");
            if (string.IsNullOrEmpty(message)) throw new ArgumentNullException("message");

            var arg = new List<QueryParameter>();
            arg.Add("uids", uids);
            arg.Add("emails", emails);
            arg.Add("subject", subject);
            arg.Add("message", message);
            arg.Add("frommail", frommail);
            arg.Add("charset", charset);
            arg.Add("htmlon", htmlon);
            arg.Add("level", level);

            return ToInt(uc_api_post("mail", "add", arg));
        }

        /// <summary>
        /// 检测uc_server的数据库版本和程序版本
        /// </summary>
        /// <returns>
        /// array('db' => 'xxx', 'file' => 'xxx');
        /// null 无法调用到接口
        /// string 文件版本低于1.5
        /// </returns>
        public static object uc_check_version()
        {
            var resultStr = uc_api_post("version", "check");
            var result = XmlHelper.UnSerialize(resultStr);

            if (result != null) return result;
            return resultStr;
        }

        #endregion 系统接口

        #endregion API

    }
}
